/* 上传资源（图片，视频等，可自行扩展）相关逻辑 */
import { ElMessage, type UploadFile } from "element-plus";
import { chackImageType, chackVideoType } from "@/shared/index.ts";
import { getUploadToken } from "@/utils/api/mallGoods";
import type { ISuffix, IUpdateSuccessData, IUpload, IUploadData, IUpToken, IBeforeUpload } from "@/types/upload";

/* 上传文件类型映射 */
const resourceMap = {
  ".xls": "application/vnd.ms-excel",
  ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  ".pdf": "application/pdf",
  ".csv": "text/csv"
};
/* 上传图片类型映射 */
const imageMap = {
  ".png": "image/png",
  ".jpg": "image/jpeg",
  ".jpeg": "image/jpeg",
  ".gif": "image/gif",
  ".webp": "image/webp",
  ".svg": "image/svg+xml"
};
/* 上传文件类型映射key */
type ResourceKey = keyof typeof resourceMap;
/* 上传图片类型映射key */
type ImageKey = keyof typeof imageMap;
/**
 * 上传资源到七牛云的自定义Hook
 * 提供图片和视频上传前的校验、上传凭证获取以及上传成功和失败的处理逻辑
 * @param {IUpload} options - 上传控制参数
 * @param {Ref<boolean>} options.disabledbtn - 是否禁用上传按钮（可选）
 * @param {Ref<boolean>} options.loading - 上传加载状态
 * @returns {Object} - 包含上传数据和处理函数的对象
 * @returns {IUploadData} returns.uploadData - 上传凭证数据，包含token和key(以后可以做成，前端自己生成key)
 * @returns {Function} returns.handleBeforeUpload - 图片上传前的校验和凭证获取函数
 * @returns {Function} returns.handleBeforeVideoUpload - 视频上传前的校验和凭证获取函数
 * @returns {Function} returns.handleResourcesUploadSuccess - 图片上传成功的处理函数
 * @returns {Function} returns.handleResourcesUploadError - 图片上传失败的处理函数
 */
export const useUpload = ({ disabledbtn, loading }: IUpload) => {
  /* 上传图片到七牛云的token与图片名称 */
  const uploadData: IUploadData = { token: "", key: "" };
  /**
   * 图片上传成功（暂不考虑对象嵌套深的情况）
   * @param {object} response 七牛云返回的资源信息
   * @param {function} successCallback 自定义执行函数（传入上传成功的地址）
   */
  function handleResourcesUploadSuccess(response: IUpdateSuccessData, file: UploadFile, successCallback?: (res: IUpdateSuccessData, file: UploadFile) => void) {
    if (loading) {
      loading.value = false;
    }
    if (disabledbtn) {
      disabledbtn.value = false;
    }
    if (successCallback) {
      successCallback(response, file);
    }
  }

  /**
   * 图片上传失败的回调
   */
  function handleResourcesUploadError() {
    if (loading) {
      loading.value = false;
    }
    if (disabledbtn) {
      disabledbtn.value = false;
    }
    ElMessage.warning("上传失败，请联系管理员，或者刷新页面重试");
  }

  /**
   * 上传图片之前的操作（图片大小判断,类型判断，自定义图片名称与上传token，还可以做图片的压缩，压缩功能暂时没做）
   * @param {File} file 图片资源
   * @param {number} limit 图片大小限制
   * @param {function} customerBefore 自定义添加自定义上传之前的操作（如自定义校验）
   * @param {function} errorCallback 错误处理自定义执行函数
   * @returns
   */
  async function handleBeforeUpload({ file, limit = 500, fileType = ".png,.jpg,.jpeg,.gif", customerBefore, errorCallback }: IBeforeUpload) {
    if (customerBefore && !customerBefore(file)) return false;
    if (fileType == "") {
      ElMessage.error("请传入需要上传图片的格式，如'.png,.jpg'这样的格式");
      return false;
    }
    const chackType: string[] = [];
    const fileTypeList = fileType.split(",");
    fileTypeList.forEach((item: string) => {
      const key = item as ImageKey;
      chackType.push(imageMap[key]);
    });
    if (!chackType.includes(file.type)) {
      ElMessage.warning(`请上传${fileType}后缀格式的图片!`);
      if (errorCallback) {
        errorCallback(file);
      }
      return false;
    }
    if (!chackImageType(file.type)) {
      ElMessage.warning(`请上传图片!`);
      if (errorCallback) {
        errorCallback(file);
      }
      return false;
    }
    if (loading) {
      loading.value = true;
    }
    if (disabledbtn) {
      disabledbtn.value = true;
    }
    const isLimit = file.size / 1024 <= limit;
    if (!isLimit) {
      ElMessage.warning(`上传图片大小不能超过${limit}K,请压缩后再上传!`);
      if (loading) {
        loading.value = false;
      }
      if (disabledbtn) {
        disabledbtn.value = false;
      }
      if (errorCallback) {
        errorCallback(file);
      }
      return false;
    }
    const suffix = file.type.split("/")[1];
    return useResourceToken(suffix);
  }
  /**
   * 上传视频之前的操作（视频大小判断,类型判断，自定义图片名称与上传token，还可以做图片的压缩，压缩功能暂时没做）
   * @param {File} file 视频资源
   * @param {number} limit 视频大小限制
   * @returns
   */
  async function handleBeforeVideoUpload({ file, limit = 10 }: IBeforeUpload) {
    if (!chackVideoType(file.type)) {
      ElMessage.warning(`请上传视频!`);
      return false;
    }
    if (loading) {
      loading.value = true;
    }
    if (disabledbtn) {
      disabledbtn.value = true;
    }
    const isLimit = file.size / 1024 / 1024 <= limit;
    if (!isLimit) {
      ElMessage.warning(`上传视频大小不能超过${limit}M,请压缩后再上传!`);
      if (loading) {
        loading.value = false;
      }
      if (disabledbtn) {
        disabledbtn.value = false;
      }
      return false;
    }
    const suffix = file.type.split("/")[1];
    return useResourceToken(suffix);
  }

  /**
   * 上传 资源 之前的操作
   * @param {File} file xls xlsx pdf 等资源
   * @param {number} limit 资源大小限制 默认1M
   * @param {function} customerBefore 自定义添加自定义上传之前的操作（如自定义校验）
   * @param {function} errorCallback 错误处理自定义执行函数
   * @returns
   */
  async function handleBeforeResourceUpload({ file, limit = 1, fileType = "", customerBefore, errorCallback }: IBeforeUpload) {
    if (customerBefore && !customerBefore(file)) return false;
    if (fileType == "") {
      ElMessage.error("请传入需要上传文件的文件格式，如'.pdf,.xls'这样的格式");
      return false;
    }
    const chackResourceType: string[] = [];
    const fileTypeList = fileType.split(",");
    fileTypeList.forEach((item: string) => {
      const key = item as ResourceKey;
      chackResourceType.push(resourceMap[key]);
    });
    if (!chackResourceType.includes(file.type)) {
      ElMessage.warning(`请上传${fileType}后缀格式的文件!`);
      if (errorCallback) {
        errorCallback(file);
      }
      return false;
    }
    if (loading) {
      loading.value = true;
    }
    if (disabledbtn) {
      disabledbtn.value = true;
    }
    const isLimit = file.size / 1024 / 1024 <= limit;
    if (!isLimit) {
      ElMessage.warning(`上传文件大小不能超过${limit}M，请压缩后上传!`);
      if (loading) {
        loading.value = false;
      }
      if (disabledbtn) {
        disabledbtn.value = false;
      }
      if (errorCallback) {
        errorCallback(file);
      }
      return false;
    }
    const suffix = file.name.split(".")[1];
    return useResourceToken(suffix);
  }

  /* 获取上传的token */
  function useResourceToken(suffix: string): Promise<void> {
    /* 获取七牛云token */
    return getUploadToken<IUpToken, ISuffix>({ suffix })
      .then(res => {
        uploadData.key = res.result.fileName[0];
        uploadData.token = res.result.upToken;
      })
      .catch(() => {});
  }

  return {
    uploadData: () => uploadData /* 这一步，返回一个函数是很有必要的，做数据隔离 */,
    handleBeforeVideoUpload,
    handleBeforeResourceUpload,
    handleResourcesUploadSuccess,
    handleBeforeUpload,
    handleResourcesUploadError
  };
};
